package org.yys.seata.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yys.seata.constants.TccStatusConstant;
import org.yys.seata.entity.AccountEntity;
import org.yys.seata.entity.AccountFreezeEntity;
import org.yys.seata.service.AccountFreezeService;
import org.yys.seata.service.AccountService;
import org.yys.seata.service.AccountTCCService;

@Service
@Slf4j
@Transactional
public class AccountTCCServiceImpl implements AccountTCCService {

    @Autowired
    private AccountService accountService;

    @Autowired
    private AccountFreezeService accountFreezeService;

    @Override
    public void tryDecrease(Long userId, Integer money) {
        String xid = RootContext.getXID();

        // 业务悬挂判断
        AccountFreezeEntity oldAccountFreeze = accountFreezeService.getById(xid);
        if(oldAccountFreeze!=null){
            return;
        }

        // 1. 查询账户并将金额冻结在冻结表中
        LambdaQueryWrapper<AccountEntity> eq = Wrappers.<AccountEntity>lambdaQuery().eq(AccountEntity::getUserId, userId);
        AccountEntity one = accountService.getOne(eq);

        if (one==null) {
            throw new RuntimeException("账户为空");
        }


        one.setResidue(one.getResidue()-money);
        one.setUsed(one.getUsed()+money);

        accountService.updateById(one);


        AccountFreezeEntity accountFreezeEntity = new AccountFreezeEntity();
        accountFreezeEntity.setXid(xid);
        accountFreezeEntity.setUserId(userId);
        accountFreezeEntity.setFreezeMoney(money);
        accountFreezeEntity.setState(TccStatusConstant.TRY);
        accountFreezeService.save(accountFreezeEntity);
    }

    @Override
    public boolean commitDecrease(BusinessActionContext context) {
        String xid = context.getXid();

        // 删除冻结表
        boolean b = accountFreezeService.removeById(xid);

        return b;
    }

    @Override
    public boolean cancelDecrease(BusinessActionContext context) {
        String xid = context.getXid();

        // 查询冻结表
        AccountFreezeEntity accountFreezeEntity = accountFreezeService.getById(xid);
        // 空回滚判断
        if(accountFreezeEntity==null){
            // try没执行的情况下, 执行空回滚
            Object userId = context.getActionContext("userId");

            accountFreezeEntity=new AccountFreezeEntity();
            accountFreezeEntity.setXid(xid);
            accountFreezeEntity.setUserId((Long) userId);
            accountFreezeEntity.setFreezeMoney(0);
            accountFreezeEntity.setState(TccStatusConstant.CANCEL);

            accountFreezeService.save(accountFreezeEntity);

            return true;
        }
        // 幂等性保证
        if(accountFreezeEntity.getState().equals(TccStatusConstant.CANCEL)){
            return true;
        }

        Long userId = accountFreezeEntity.getUserId();
        Integer freezeMoney = accountFreezeEntity.getFreezeMoney();


        // 根据冻结表还原剩余金额, 并更新状态
        LambdaQueryWrapper<AccountEntity> eq = Wrappers.<AccountEntity>lambdaQuery().eq(AccountEntity::getUserId, userId);
        AccountEntity one = accountService.getOne(eq);
        if (one==null) {
            throw new RuntimeException("账户为空");
        }

        one.setResidue(one.getResidue()+freezeMoney);
        one.setUsed(one.getUsed()-freezeMoney);

        accountService.updateById(one);

        accountFreezeEntity.setState(TccStatusConstant.CANCEL);
        accountFreezeEntity.setFreezeMoney(0);
        accountFreezeService.updateById(accountFreezeEntity);

        return true;
    }
}
